package com.itheima.a05;

import com.itheima.a05.mapper.Mapper1;
import com.itheima.a05.mapper.Mapper2;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.awt.*;
import java.io.IOException;
import java.util.Set;

/**
 * @author: AirMan
 * @date: 2025/4/10 18:17
 * @description:
 */
public class MyA05 {
    public static void main(String[] args) throws IOException {

        // ⬇️GenericApplicationContext 是一个【干净】的容器
        GenericApplicationContext context = new GenericApplicationContext();

        context.registerBean("config", Config.class);

        // ConfigurationClassPostProcessor BeanFactory后处理器
        // =》解析 @Component @Bean @Import @ImportResource
//        context.registerBean(ConfigurationClassPostProcessor.class);


        /* 模拟 ConfigurationClassPostProcessor 中ComponentScan的处理过程 */
//        MyComponentScanPostProcess componentScanPostProcess = new MyComponentScanPostProcess();
//        componentScanPostProcess.postProcessBeanDefinitionRegistry(context);
//        ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
//        if (componentScan != null) {
//            for (String p : componentScan.basePackages()) {
//                // 将 com.itheima.a05.component 修改为 classpath*:com/itheima/a05/mapper/**/*.class
//                String path = "classpath*:" + p.replace(".", "/") + "/**/*.class";
//                CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
//                Resource[] resources = context.getResources(path);
//                AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();
//                for (Resource resource : resources) {
//                    MetadataReader reader = factory.getMetadataReader(resource);
//                    System.out.println("resource = " + resource);
//                    String className = reader.getClassMetadata().getClassName();
//                    System.out.println("className = " + className);
//                    System.out.println("是否存在Component注解 = " + reader.getAnnotationMetadata().hasAnnotation(Component.class.getName()));
//                    System.out.println("是否存在Component衍生注解 = " + reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName()));
//                    // 注册 Bean
//                    if (reader.getAnnotationMetadata().hasAnnotation(Component.class.getName())
//                            || reader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName())) {
//                        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(reader.getClassMetadata().getClassName())
//                                .getBeanDefinition();
//                        String beanName = generator.generateBeanName(beanDefinition, context);
//                        context.registerBeanDefinition(beanName, beanDefinition);
//                        System.out.println(">>>>>>>>>>>>>注册bean：" + beanName);
//                    }
//                }
//            }
//        } else {
//            System.out.println("componentScan是空的");
//        }

        // 解析 @MapperScan
//        context.registerBean(MapperScannerConfigurer.class, () -> {
//            MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//            mapperScannerConfigurer.setBasePackage("com.itheima.a05.mapper");
//            return mapperScannerConfigurer;
//        });

//        // 解析 @MapperScan
//        context.registerBean(MapperScannerConfigurer.class, db -> {
//            db.getPropertyValues().add("basePackage", "com.itheima.a05.mapper");
//        });
//
//        // 解析 @Mapper （前提是需要解析 @MapperScan ）
//        context.registerBean(MapperScannerConfigurer.class, () -> {
//            MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
//            mapperScannerConfigurer.setBasePackage("com.itheima.a05.mapper");
//            return mapperScannerConfigurer;
//        });



        /* 模拟 ConfigurationClassPostProcessor 中Bean的处理过程 */
//        String path = "classpath*:" + "com/itheima/a05" + "/**/*class";
//        Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
//        for (Resource resource : resources) {
//            System.out.println("resource = " + resource);
//            CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
//            MetadataReader reader = factory.getMetadataReader(resource);
//            Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
//            String classAllName = reader.getClassMetadata().getClassName();
//            String className = classAllName.substring(classAllName.lastIndexOf(".") + 1).toLowerCase();
//            for (MethodMetadata method : methods) {
//                // 配置类充当的是一个工厂的角色，被 @Bean 注解的方法就是工厂方法
//                // 这里就不采用类名设置，我们把方法当作工厂方法
//                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
//                // 设置工厂方法, 工厂方法名，工厂bean就是当前的类（已经被 spring 进行管理了）
//                builder.setFactoryMethodOnBean(method.getMethodName(), className);
//                // 注解的属性解析
//                String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
//                // 开启构造方法和工厂方法的自动装配
//                builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
//                if (!initMethod.isEmpty()) {
//                    System.out.println("参数自动装配方法：" + initMethod);
//                    builder.setInitMethodName(initMethod);
//                }
//                // 获取 beanDefinition
//                AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
//                // 注册 bean
//                context.registerBeanDefinition(method.getMethodName(), beanDefinition);
//            }
//        }
        context.registerBean(MyBeanPostProcessor.class); // 解析 Bean

        /* 模拟 Mapper 接口的处理过程 */
        context.registerBean(MyMapperPostProcessor.class); // 解析 Mapper

        // ⬇️初始化容器
        context.refresh();
//
//        Mapper1 mapper1 = context.getBean(Mapper1.class);
//        Mapper2 mapper2 = context.getBean(Mapper2.class);

        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }

        // ⬇️销毁容器
        context.close();
    }
}
